package com.sharp.core.voxel;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

import com.jme3.app.SimpleApplication;
import com.jme3.asset.AssetManager;
import com.jme3.collision.CollisionResult;
import com.jme3.collision.CollisionResults;
import com.jme3.font.BitmapFont;
import com.jme3.font.BitmapText;
import com.jme3.input.InputManager;
import com.jme3.input.MouseInput;
import com.jme3.input.controls.ActionListener;
import com.jme3.input.controls.MouseButtonTrigger;
import com.jme3.light.DirectionalLight;
import com.jme3.material.Material;
import com.jme3.material.RenderState.BlendMode;
import com.jme3.material.RenderState.FaceCullMode;
import com.jme3.math.ColorRGBA;
import com.jme3.math.Ray;
import com.jme3.math.Vector3f;
import com.jme3.renderer.queue.RenderQueue.Bucket;
import com.jme3.scene.Geometry;
import com.jme3.scene.Mesh;
import com.jme3.scene.Node;
import com.jme3.scene.Mesh.Mode;
import com.jme3.scene.Spatial.CullHint;
import com.jme3.scene.VertexBuffer.Type;
import com.jme3.scene.shape.Box;
import com.jme3.util.BufferUtils;
import com.sharp.core.voxel.resource.Vox;


public class HelloWorld extends SimpleApplication {

	Node voxelPivot;
	Geometry red;
	Geometry lastHit;
	public static AssetManager asd;
	
	public static AssetManager anyad() {
		return asd;
	}
	
	private ActionListener actionListener = new ActionListener() {
		private boolean state;
		@Override
		public void onAction(String name, boolean isPressed, float tpf) {
			if ( name.equals("Shoot") ) {
				inputManager.setCursorVisible(state=!state);
				CollisionResults results = new CollisionResults();
				Ray ray = new Ray(cam.getLocation(), cam.getDirection());
				voxelPivot.collideWith(ray, results);
				if ( results.size() > 0 ) {
					if ( lastHit != null )
						lastHit.getMaterial().setColor("Color", ColorRGBA.Black);
					lastHit = results.getClosestCollision().getGeometry();
					lastHit.getMaterial().setColor("Color", ColorRGBA.Red);
				} else {
					if ( lastHit != null )
						lastHit.getMaterial().setColor("Color", ColorRGBA.Black);
				}
			}
		}
	};
	
	public static void main(String[] args) {
		new HelloWorld().start();
	}

	private void initKeys() {
		inputManager.addMapping("Shoot",new MouseButtonTrigger(MouseInput.BUTTON_LEFT));
		inputManager.addListener(actionListener, "Shoot");
	}
	
	@Override
	public void simpleInitApp() {
		asd = assetManager;
		
		inputManager.setCursorVisible(true);
		Box box1 = new Box(new Vector3f(0, 0, 0), 1, 1, 1);
		Geometry blue= new Geometry("Box", box1);
		Material mat1 = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
		mat1.setColor("Color", ColorRGBA.Blue);
		blue.setMaterial(mat1);
		
		Box box2 = new Box(new Vector3f(1, 3, 1), 1, 1, 1);
		red= new Geometry("Box", box2);
		Material mat2 = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
		mat2.setColor("Color", ColorRGBA.Red);
		mat2.getAdditionalRenderState().setBlendMode(BlendMode.Alpha);
		red.setMaterial(mat2);
		red.setQueueBucket(Bucket.Transparent);
		
		Node pivot = new Node("pivot");
		Node pivot2 = new Node("pivot");
		rootNode.attachChild(pivot);
		rootNode.attachChild(pivot2);
		
		//pivot.attachChild(blue);
		//pivot.attachChild(red);

		flyCam.setMoveSpeed(50);
		
		voxelPivot = new Node("voxelPivot");
		rootNode.attachChild(voxelPivot);
		//pivot.rotate(0.4f, 0.4f, 0.0f);
		try {
			Vox vox = (Vox) VoxelLoader.load("data/desklamp.vox");
			VoxelArray array = vox.convertToVoxelArray();
			
			VoxelRenderList list = new Polygonizator().polygonize(array, 1, 0.5f);
				
			Mesh m = new Mesh();
			m.setBuffer(Type.Position, 3, BufferUtils.createFloatBuffer(list.getVertices()));
			m.setBuffer(Type.Color, 4, BufferUtils.createFloatBuffer(list.getColors()));
			//m.setMode(Mesh.Mode.Lines);
			m.updateBound();
			m.setStatic();
			//m.setBuffer(Type.Index, 1, BufferUtils.createIntBuffer(indices));
				
			Geometry geom = new Geometry("myMesh", m);
			Material mat = new Material(assetManager, "Common/MatDefs/Misc/VertexColor.j3md");
			mat.getAdditionalRenderState().setFaceCullMode(FaceCullMode.Off);
			geom.setMaterial(mat);
			//pivot2.attachChild(geom);
			
		} catch (IOException e) {
			e.printStackTrace();
		}
		
		VoxelArray arr = new VoxelArray(3, 3, 3);
		arr.setVoxel(1, 1, 1, new Voxel(new ColorRGBA(ColorRGBA.White)));
		for ( int x = 0; x < arr.getWidth(); ++x ) {
			for ( int y = 0; y < arr.getHeight(); ++y ) {
				for ( int z = 0; z < arr.getDepth(); ++z ) {
					Box box = new Box(new Vector3f(x, y, z), 1, 1, 1);
					Geometry geom = new Geometry("Cube", box);
					Material mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
					mat.setColor("Color", ColorRGBA.Blue);
					box.setMode(Mode.LineStrip);
					box.setLineWidth(2);
					geom.setMaterial(mat);
					//pivot2.attachChild(geom);
				}
			}
		}
		
		
		VoxelRenderList list = new Polygonizator().polygonize(arr, 1, 0.5f);
		Mesh m = new Mesh();
		m.setBuffer(Type.Position, 3, BufferUtils.createFloatBuffer(list.getVertices()));
		m.setBuffer(Type.Color, 4, BufferUtils.createFloatBuffer(list.getColors()));
		//m.setMode(Mesh.Mode.Lines);
		m.setLineWidth(5);
		m.setPointSize(5);
		m.updateBound();
		m.setStatic();
		//m.setBuffer(Type.Index, 1, BufferUtils.createIntBuffer(indices));
			
		Geometry geom = new Geometry("myMesh", m);
		Material mat = new Material(assetManager, "Common/MatDefs/Misc/VertexColor.j3md");
		mat.getAdditionalRenderState().setFaceCullMode(FaceCullMode.Back);
		geom.setMaterial(mat);
		pivot2.attachChild(geom);
		
		int[] kaka = {0, 0, 0};
		float[][][] map ={ {
		               		{0, 0, 0},
		               		{0, 1, 0},
		               		{0, 0, 0}
		               },
		               {
		               		{0, 0, 0},
		               		{0, 1, 0},
		               		{0, 0, 0}
		               },
		               {
		               		{0, 0, 0},
		               		{0, 1, 0},
		               		{0, 0, 0}
		               }};
		Poly2 poly = new Poly2(kaka, map, null);
		//pivot2.attachChild(poly);
		initKeys();
	}

	@Override
	public void simpleUpdate(float tpf) {
		voxelPivot.rotate(0, -tpf, 0);
	}
	
	
}
